using SaToken.SaToken.util;

namespace SaToken.SaToken.Application;

/// <summary>
/// 对取值的一组方法封装
/// <para> 封装 SaStorage、SaSession、SaApplication 等存取值的一些固定方法，减少重复编码 </para>
/// </summary>
public interface ISaGetValueInterface
{
    // --------- 需要子类实现的方法 

    /// <summary>
    /// 取值
    /// </summary>
    /// <param name="key">键</param>
    /// <returns>值</returns>
    T Get<T>(string key);


    // --------- 接口提供封装的方法 

    /// <summary>
    /// 取值（指定默认值）
    /// </summary>
    /// <typeparam name="T">默认值的类型</typeparam>
    /// <param name="key">键</param>
    /// <param name="defaultValue">取不到值时返回的默认值</param>
    /// <returns>值</returns>
    T Get<T>(string key, T defaultValue)
    {
        // 如果值为null或空字符串，则直接返回默认值
        var result = Get<T>(key);
        return ValueIsNull(result)
            ? defaultValue
            : result;
    }

    /// <summary>
    /// 取值（转string类型）
    /// </summary>
    /// <param name="key">键</param>
    /// <returns>值</returns>
    string GetString(string key)
    {
        var value = Get(key);
        return value.ToString() ?? string.Empty;
    }

    /// <summary>
    /// 取值（转int类型）
    /// </summary>
    /// <param name="key">键</param>
    /// <returns>值</returns>
    int? GetInt32(string key)
    {
        var value = Get(key);
        return ValueIsNull(value)
            ? null
            : int.Parse((string)value);
    }

    /// <summary>
    /// 取值（转long类型）
    /// </summary>
    /// <param name="key">键</param>
    /// <returns>值</returns>
    long GetInt64(string key)
    {
        return GetValueByDefaultValue(Get(key), 0L);
    }

    /// <summary>
    /// 取值（转double类型）
    /// </summary>
    /// <param name="key">键</param>
    /// <returns>值</returns>
    double GetDouble(string key)
    {
        return GetValueByDefaultValue(Get(key), 0.0);
    }

    /// <summary>
    /// 取值（转float类型）
    /// </summary>
    /// <param name="key">键</param>
    /// <returns>值</returns>
    float GetSingle(string key)
    {
        return GetValueByDefaultValue(Get(key), 0.0f);
    }


    /// <summary>
    /// 取值（指定转换类型，并指定值为 null 时返回的默认值）
    /// </summary>
    /// <typeparam name="T">目标类型</typeparam>
    /// <param name="key">键</param>
    /// <param name="type">指定转换类型</param>
    /// <param name="defaultValue">值为Null时返回的默认值</param>
    /// <returns>值</returns>
    T GetModel<T>(string key, Type type, T defaultValue)
    {
        var model = GetModel<T>(key, type);
        return ValueIsNull(model) ? defaultValue : model;
    }

    /// <summary>
    /// 是否含有某个 key
    /// </summary>
    /// <param name="key">指定 key</param>
    /// <returns>是否含有</returns>
    bool Has(string key)
    {
        return !ValueIsNull(Get(key));
    }

    // --------- 内部工具方法 
    /// <summary>
    /// 判断一个值是否为null或空字符串
    /// </summary>
    /// <param name="value">指定值</param>
    /// <returns>此value是否为null或空字符串</returns>
    bool ValueIsNull(object? value)
    {
        return value switch
        {
            // 1. 先判断 null（最直接的空值情况）
            null => true,
            // 2. 针对 string 类型单独优化（避免多余的 ToString() 调用）
            string str => string.IsNullOrEmpty(str),
            _ => value.ToString() == string.Empty
        };
    }
}